package fclient

import (
	"dmsv/callrouter"
	"errors"
	"fmt"
	"github.com/beego/beego/v2/core/logs"
	"strings"
)

/*
发起外呼
caller : 主叫
callee : 被叫
router : 被叫路由
dir    : 呼叫类型（坐席、客户）
wait   : 外呼等待时长
*/
func OutCall(caller, callee, router string, wait int) (string, error) {

	callId, err := gHandler.conn.Api("create_uuid")
	if nil != err {
		return "", errors.New("create uuid" + err.Error())
	}

	args := fmt.Sprintf("{origination_uuid=%s,call_timeout=%d,origination_caller_id_number=%s}sofia/external/%s@%s &park()",
		callId, wait, caller, callee, router)

	bgJobId, err := gHandler.conn.BgApi("originate", args)
	if err != nil {
		return "", errors.New("originate" + err.Error())
	}

	gHandler.bgJob.Store(bgJobId, callId)
	logs.Debug("[%v] caller:%v ,callee:%v,外呼Id:%v", callId, caller, callee, bgJobId)

	return callId, nil
}

/*
呼叫本地坐席
display : 主叫
service : 被叫
*/
func CallLocalService(display, service string) (string, error) {

	callId, err := gHandler.conn.Api("create_uuid")
	if nil != err {
		return "", errors.New("create uuid" + err.Error())
	}

	args := fmt.Sprintf("{origination_uuid=%s,origination_caller_id_number=%s}user/%s &park()",
		callId, display, service)

	logs.Debug("[%v] 外呼指令：%v", callId, args)
	bgJobId, err := gHandler.conn.BgApi("originate", args)
	if err != nil {
		logs.Error("call local service:[%v]  failed:%v", service, err)
		return "", errors.New("originate" + err.Error())
	}

	gHandler.bgJob.Store(bgJobId, callId)
	logs.Debug("[%v] caller:%v ,callee:%v, bgjobId:%v", callId, display, service, bgJobId)

	return callId, nil
}

func NewCallId() (string, error) {
	uuid, err := gHandler.conn.Api("create_uuid")
	if nil != err {

		return "", errors.New("create uuid" + err.Error())
	}
	return uuid, nil
}

func BridgeCall(afCallId, uuid, caller, callee string) error {

	//获取外呼路由
	addr, _ := callrouter.GetRouterByNum(caller, callee)

	args := fmt.Sprintf("{origination_uuid=%s,call_timeout=%d,origination_caller_id_number=%s}sofia/external/%s@%s",
		uuid, 60, caller, callee, addr)
	logs.Debug("开始桥接外呼：%v", args)
	ev, err := gHandler.conn.Execute("bridge", afCallId, args)
	if err != nil {
		return errors.New("bridge" + err.Error())
	}
	if "+OK" != ev.Get("Reply-Text") {
		logs.Error("bridge failed:%v", ev)
		return errors.New("bridge failed")
	}

	return nil
}

func BridgeTwoCall(aCallId, bCallId string) error {

	ev, err := gHandler.conn.Api("uuid_bridge", aCallId, bCallId)
	if err != nil {
		return errors.New("bridge" + err.Error())
	}
	logs.Debug("桥接两路通话:[%v],[%v]result:%v", aCallId, bCallId, ev)
	/*
		if "+OK" != ev.Get("Reply-Text") {
			logs.Error("bridge failed:%v", ev)
			return errors.New("bridge failed")
		}
	*/
	return nil
}

//挂机
func Hangup(callId string) error {
	_, err := gHandler.conn.Api("uuid_kill", callId)
	if err != nil {
		logs.Error("[%v] hangup err:%v", callId, err)
	}
	return err
}

//放音
func PlayMediaFile(callId, mediaFile string) error {

	_, err := gHandler.conn.Execute("playback", callId, mediaFile)
	if err != nil {
		return err
	}

	return nil
}

//停止放音
func StopPlay(callId string) error {

	_, err := gHandler.conn.Execute("break", callId)
	if err != nil {
		return err
	}

	return nil
}

//接听
func Answer(callId string) error {
	_, err := gHandler.conn.Api("uuid_answer", callId)
	//_, err := gHandler.conn.Execute("uuid_answer", callId)
	if err != nil {
		return err
	}

	return nil
}

type DTMF_ARGS struct {
	KeyStop    bool   //按键停止播放音乐
	EndKey     string //按键停止收集
	MaxKey     int    //最多收取按键个数,0为一直接收
	TimeOut    int    //超时时间
	KeyTimeOut int    //按键间隔时间
	MediaFile  string //放音文件
	PlayTimes  int
}

//放音获取按键
func PlayAndGetKeySimple(callId, playFile string, maxKey int) error {

	args := DTMF_ARGS{
		MediaFile: playFile,
		MaxKey:    maxKey,
	}

	if args.EndKey == "" {
		args.EndKey = "#"
	}

	if args.MaxKey == 0 {
		args.MaxKey = 1
	}

	if args.TimeOut == 0 {
		args.TimeOut = 30
	}

	if args.PlayTimes == 0 {
		args.PlayTimes = 1
	}

	ev, err := gHandler.conn.Execute("play_and_get_digits", callId,
		"1",                               //最少按键
		fmt.Sprintf("%d", args.MaxKey),    //最大按键
		fmt.Sprintf("%d", args.PlayTimes), //放音次数
		fmt.Sprintf("%d", args.TimeOut),   //总时长
		fmt.Sprintf("%s", args.EndKey),    //终止按键
		fmt.Sprintf("%s", args.MediaFile)) //播放语音
	//"silence_stream://5000") //停顿时长后再回调play stop

	if err != nil {
		logs.Error("[%v]get dtmf failed:%v", callId, err)
		return fmt.Errorf("ErrCmdSend:%v", err)
	}

	result := ev.Get("Reply-Text")
	if !strings.Contains(result, "OK") {
		logs.Error("[%v]get key excute failed:%v", callId, result)
		return fmt.Errorf("ErrExcuse:%v", result)
	}

	return nil
}

//放音获取按键
func PlayAndGetKey(callId string, args DTMF_ARGS) error {

	if args.EndKey == "" {
		args.EndKey = "#"
	}

	if args.MaxKey == 0 {
		args.MaxKey = 1
	}

	if args.TimeOut == 0 {
		args.TimeOut = 30
	}

	if args.PlayTimes == 0 {
		args.PlayTimes = 1
	}

	ev, err := gHandler.conn.Execute("play_and_get_digits", callId,
		"1",                               //最少按键
		fmt.Sprintf("%d", args.MaxKey),    //最大按键
		fmt.Sprintf("%d", args.PlayTimes), //放音次数
		fmt.Sprintf("%d", args.TimeOut),   //总时长
		fmt.Sprintf("%s", args.EndKey),    //终止按键
		fmt.Sprintf("%s", args.MediaFile)) //播放语音
	//"silence_stream://5000") //停顿时长后再回调play stop
	if err != nil {
		logs.Error("[%v]get dtmf failed:%v", callId, err)
		return fmt.Errorf("ErrCmdSend:%v", err)
	}

	result := ev.Get("Reply-Text")
	if !strings.Contains(result, "OK") {
		logs.Error("[%v]get key excute failed:%v", callId, result)
		return fmt.Errorf("ErrExcuse:%v", result)
	}

	return nil
}

//录音
func Record(callId, filePath string) error {

	ev, err := gHandler.conn.Api("uuid_record", callId, "start", filePath)
	if err != nil {
		return err
	}

	if strings.Contains(ev, "ERR") {
		return fmt.Errorf("ErrRecord:%v", ev)
	}

	return nil
}

func SetNoHangUpAfterUnbridge(callId string) error {

	ev, err := gHandler.conn.Execute("set", callId, "hangup_after_bridge=false")
	if err != nil {
		logs.Error("%v 设置桥接结束不挂机失败:%v,err:%v", callId, ev, err.Error())
		return err
	}

	ev, err = gHandler.conn.Execute("set", callId, "park_after_bridge=true")
	if err != nil {
		logs.Error("%v 设置桥接结束park失败:%v,err:%v", callId, ev, err.Error())
		return err
	}
	return nil
}

func LoadSipAcct() error {
	res, err := gHandler.conn.Api("reloadxml")

	if strings.Contains(res, "OK") {
		return nil
	} else {
		logs.Error("load xml failed:%v", res)
	}

	return err
}

func DelRegAcct(acct, domain string) error {

	args := fmt.Sprintf("profile internal flush_inbound_reg %s@%s", acct, domain)
	//sofia profile internal flush_inbound_reg 18621575908@10.0.0.21
	res, err := gHandler.conn.Api("sofia", args)
	logs.Info("cmd:%v ;remove sipper:%v", args, res)
	if strings.Contains(res, "OK") {
		return nil
	} else {
		logs.Error("load xml failed:%v", res)
	}
	return err
}
